﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq;
using System.IO;
using System.Security.Cryptography;

namespace ConsoleApplication1
{
    class DBClass
    {
        public Dictionary<int, int> sortedNumOfAppearenceInRepository;// all hashed ngram and it num of appearence in repository
        public List<int> topNgrams; // keeps the top nGram that we want to save from all the nGrams
        public List<Document> allDocuments { get; set; } // key-document name
        public Dictionary<string, List<double>> tfidfDic; //for every document, foreach ngram in topngram keeps the tf*idf

        public DBClass()
        {
            allDocuments = new List<Document>();
            sortedNumOfAppearenceInRepository = new Dictionary<int, int>();
            topNgrams = new List<int>();
            tfidfDic = new Dictionary<string, List<double>>();
        }
        /// <summary>
        /// create all the documents, run the function: "HandleText" wich responsible for the nGram  
        /// </summary>
        /// <param name="docs"></param>
        /// <param name="k"></param>
        /// <param name="n"></param>
        /// <param name="toSort"></param>
        public void CreateAllDocuments(Dictionary<string, string> docs, int k, int n, bool toSort)
        {
            foreach (KeyValuePair<string, string> currentDoc in docs)
            {
                Document d = new Document(currentDoc.Key, currentDoc.Value);
                d.MakeNGramsFromText(k, n, toSort);
                d.CreateFingerPrints(3, 1, true);
                allDocuments.Add(d);
            }
        }


        /// <summary>
        /// this function update the global count of n gram in documents
        /// </summary>
        /// <param name="DB"></param>
        /// <param name="top"></param>
        public void CreateTfIdf(int top)
        {

            foreach (Document currentDoc in allDocuments)
            {
                foreach (int currentNgram in currentDoc.m_allHashedNGrams.Keys)
                {
                    if (!sortedNumOfAppearenceInRepository.ContainsKey(currentNgram)) // not exist in dic
                        sortedNumOfAppearenceInRepository.Add(currentNgram, 1);

                    else  // exist, update num of appearence
                        sortedNumOfAppearenceInRepository[currentNgram]++;
                }
            }
            SelectTopNGrmas(top); // select to k best features
            calcultetfidf(); // calculate the weights only for the k features
        }

        /// <summary>
        /// select a number of ngram which will appear in topsNgram 
        /// </summary>
        /// <param name="DB"></param>
        /// <param name="numOfNGrams"></param>
        private void SelectTopNGrmas(int numOfNGrams)
        {
            if (numOfNGrams > sortedNumOfAppearenceInRepository.Count)
            {
                Console.WriteLine("the max size you can insert is must be smaller the total nGrams!!");
                Console.WriteLine("please insert a new number of nGrams for the feature selection which small than: " + sortedNumOfAppearenceInRepository.Count);
                numOfNGrams = int.Parse(Console.ReadLine());
            }
            sortedNumOfAppearenceInRepository = sortedNumOfAppearenceInRepository.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
            int i = 0;
            foreach (KeyValuePair<int, int> item in sortedNumOfAppearenceInRepository)
            {
                if (i == numOfNGrams)
                    return;
                else
                {
                    topNgrams.Add(item.Key);
                    i++;
                }
            }
        }
        /// <summary>
        /// calculte the tf idf for each document and foreach ngram in topngram
        /// </summary>
        /// <param name="DB"></param>
        public void calcultetfidf()
        {
            List<double> tempList = new List<double>();  // list who keeps all n gram
            foreach (Document currentDoc in allDocuments)
            {

                foreach (int currentNgram in topNgrams)  // foreach document foreach ngram making a tfidf calculating
                {
                    if (!currentDoc.m_allHashedNGrams.ContainsKey(currentNgram))// if ngram not exist in the current document
                        tempList.Add(0);
                    else
                    {
                        double idf = Math.Log((double)allDocuments.Count / (double)sortedNumOfAppearenceInRepository[currentNgram], 2);
                        double tf = (double)currentDoc.m_allHashedNGrams[currentNgram] / (double)currentDoc.m_mostCommonNGram;
                        tempList.Add(tf * idf);
                    }



                }//foreach ngram
                tfidfDic.Add(currentDoc.m_Name, new List<double>(tempList));
                tempList.Clear();
            }//foreach doc
        } //calculatetfidf
        
    }
    }


